﻿
#region  ConvertFrom-ShareReturnCode 

function ConvertFrom-ShareReturnCode ($write) 
{
    switch ($write.ReturnValue) 
    {
        "0"     {"Success"}
        "2"     {"Access Denied"}
        "8"     {"Unknown Failure"}
        "9"     {"Invalid Name"}
        "21"    {"Invalid Parameter"}
        "22"    {"Duplicate Share"}
        "23"    {"Redirected Path"}
        "24"    {"Unknown Device or Directory"}
        "25"    {"Net Name Not Found"}
        default {"Unknown error $write.ReturnValue"}
    }
}

#endregion 


#region New-Share 

function New-Share
{
    Param(
	    [alias('dnsHostName')]
		[Parameter(ValueFromPipelineByPropertyName=$true,ValueFromPipeline=$true)]
		[string]$ComputerName = $Env:COMPUTERNAME,
        
        [Parameter(Mandatory=$True)]
        [String]$Name,
        
        [Parameter(Mandatory=$True)]
        [String]$Path,
        
        [Parameter()]
        [String]$Description
        
    )

    Process
    {
        $NewShare = New-ShareObject -Name $Name                     `
                                    -ComputerName $ComputerName     `
                                    -Path $Path                     `
                                    -Description $Description       `
                                    -UserName "Everyone"            `
                                    -SID "S-1-1-0"                  `
                                    -AccessMask "FullControl"       `
                                    -ACEType "Allow"
        $NewShare | Set-Share
    }
}

#endregion 


#region Get-Share 

function Get-Share
{
    [CmdletBinding(DefaultParameterSetName="ByName")]
    Param(
	    [alias('dnsHostName')]
		[Parameter(ValueFromPipelineByPropertyName=$true,ValueFromPipeline=$true)]
		[string]$ComputerName = $Env:COMPUTERNAME,
        
        [Parameter(ParameterSetName="ByName")]
        [String]$Name,
        
        [Parameter()]
        [switch]$Admin
    )
    
    Process
    {
    
        if($ComputerName -match "(.*)(\$)$")
		{
			$ComputerName = $ComputerName -replace "(.*)(\$)$",'$1'
		}
        if ($name) 
        {
            $shares = Get-WmiObject Win32_Share -ComputerName $ComputerName -Filter "name = '$name'"
        } 
        else 
        {
            $Filter = "type = 0"
            if($Admin)
            {
                $Filter +=  " OR type = 2147483648"
            }
            $Shares = Get-WmiObject Win32_Share -ComputerName $ComputerName -Filter $Filter
        }
        
        
        $ShareDACLs = @()
        foreach ($share in $shares) 
        {
            $ShareSec = Get-WmiObject Win32_LogicalShareSecuritySetting -ComputerName $ComputerName -Filter "name='$($share.name)'" 
            if ($shareSec) 
            {
                $SD = $sharesec.GetSecurityDescriptor()
                $ShareInfo += $SD.Descriptor.DACL | % {
                    $myobj = @{
                        AccessMask = $_.AccessMask
                        AceFlags   = $_.AceFlags
                        AceType    = $_.AceType
                        UserName   = $_.trustee.Name
                        Domain     = $_.trustee.Domain
                        SID        = $_.trustee.SIDString
                    }
                    $obj = New-Object PSObject -Property $myobj
                    $obj.PSTypeNames.Clear()
                    $obj.PSTypeNames.Add('BSonPosh.Share.ACL')
                    $ShareDACLs += $obj
                }
            } 

            $myobj = @{
                ComputerName = $ComputerName
                Name         = $share.Name
                Path         = $share.Path
                Description  = $share.Description
                Access       = $ShareDACLs
            }
            
            $obj = New-Object PSObject -Property $myobj
			$obj.PSTypeNames.Clear()
			$obj.PSTypeNames.Add('BSonPosh.Share.Info')
			$obj
        }
    }
}

#endregion 


#region Set-Share

function Set-Share 
{
    [CmdletBinding()]
    Param(
        [Parameter(ValueFromPipeline=$true)]
        [Object]$ShareInfo
    )
    Process
    {
        $ComputerName = $ShareInfo.ComputerName
        $Name         = $ShareInfo.Name
        $SD           = ([WMIClass] "Win32_SecurityDescriptor").CreateInstance()
        $ace          = ([WMIClass] "Win32_Ace").CreateInstance()
        $Trustee      = ([WMIClass] "Win32_Trustee").CreateInstance()
        $SD.DACL      = @()
        
        # Creating SID Array for ACE
        $SID              = $ShareInfo.SID
        [byte[]]$SIDArray = ,0 * $SID.BinaryLength
        $SID.GetBinaryForm($SIDArray,0)
        
        # Creating ACE
        $Trustee.Name   = $ShareInfo.user
        $Trustee.SID    = $SIDArray
        $ACE.AccessMask = $ShareInfo.AccessMask
        $ACE.AceType    = $ShareInfo.AceType
        $ACE.AceFlags   = $ShareInfo.AceFlags
        $ACE.trustee    = $Trustee
        
        # Adding ACE to DACL
        $SD.DACL += $ACE.PSObject.BaseObject
        
        # Getting Share if it exist
        $Share = Get-WmiObject Win32_Share -ComputerName $ShareInfo.ComputerName -Filter "name = '$name'"
        
        if($Share) 
        {
            $inParams        = $Share.PSBase.GetMethodParameters("SetShareInfo")
            $inParams.Access = $SD
            $Result = $Share.PSBase.InvokeMethod("SetShareInfo", $inParams, $null)
            Write-Verbose " [Set-Share] :: Setting DACL on current share: $($ShareInfo.Name) on server $($ShareInfo.ComputerName)"
            ConvertFrom-ShareReturnCode $Result
        } 
        else 
        {
            $ShareObject = [wmiClass]"\\$($ShareInfo.ComputerName)\root\cimv2:win32_Share"
            $inParams             = $ShareObject.PSBase.GetMethodParameters("Create")
            $inParams.name        = $ShareInfo.Name
            $inParams.path        = $ShareInfo.Path
            $inParams.Description = $ShareInfo.Description
            $inParams.Type        = 0
            $inParams.Access      = $SD
            $Result = $ShareObject.PSBase.InvokeMethod("Create", $inParams, $null)
            Write-Verbose " [Set-Share] :: Creating share: $($ShareInfo.Name) on server $($ShareInfo.ComputerName)"
            ConvertFrom-ShareReturnCode $Result
        }
    }
    
}

#endregion 


#region Remove-Share 

function Remove-Share
{
    [CmdletBinding(SupportsShouldProcess=$true)]
    Param(
    	
	    [alias('dnsHostName')]
		[Parameter(ValueFromPipelineByPropertyName=$true,ValueFromPipeline=$true)] 
		[string]$ComputerName = $Env:COMPUTERNAME,
        
        [Parameter()]
        [String]$Name
        
    )
    Process
    {
        if($_.PSObject.TypeNames -contains "BSonPosh.Share.Info")
        {
            $MyComputerName = $_.ComputerName
            $MyName = $_.Name
        }
        else
        {
            $MyComputerName = $ComputerName -replace "(.*)(\$)$",'$1'
            $MyName = $Name
        }
        
        $Share = Get-WmiObject Win32_Share -ComputerName $MyComputerName -Filter "Name = '$MyName'"
        if (!$Share) 
        {
            Write-Warning "Specified network share doesn't exist!"
        } 
        else 
        {
            if($PSCmdlet.ShouldProcess($MyComputerName,"Deleting network share $MyName"))
            {
                $Result = $Share.delete()
                Write-Verbose " [Remove-Share] :: Deleting network share $MyName on computer $MyComputerName:"
                ConvertFrom-ShareReturnCode $Result
            }
        }
    }
}

#endregion 


#region New-ShareObject

function New-ShareObject
{
    Param(
    
		[Parameter(Mandatory=$True)]
		[string]$ComputerName,
        
        [Parameter(Mandatory=$True)]
        [String]$Name,
        
        [Parameter(Mandatory=$True)]
        [String]$Path,
        
        [Parameter(Mandatory=$True)]
        [String]$Description,
    
        [Parameter(Mandatory=$True)]
        [String]$UserName,
        
        [Parameter()]
        [String]$DomainName = [String]::Empty,
        
        [Parameter(Mandatory=$True)]
        [String]$SID,
        
        [Parameter(Mandatory=$True)]
        [String]$AceType,
        
        [Parameter(Mandatory=$True)]
        [String]$AccessMask
        
    )
 
    $masks = @{FullControl = 2032127; Change = 1245631; Read = 1179817}
    $types = @{Allow = 0; Deny = 1}
 
    
    $myobj = @{
        ComputerName = $ComputerName
        Name         = $Name
        Path         = $Path
        Description  = $Description
        User         = $UserName
        Domain       = $DomainName
        SID          = new-object Security.Principal.SecurityIdentifier($SID)
        AccessMask   = $AccessMask
        AceType      = $AceType
    }
    New-Object PSCustomObject -Property $myobj
    
}

#endregion


#region InWork

#region Set-SharePermission

function Set-SharePermission
{
    [CmdletBinding(SupportsShouldProcess=$true)]
    Param(
        
        [Parameter()]
        [String]$UserName,
        
        [Parameter()]
        [String]$AceType,
        
        [Parameter()]
        [String]$AccessMask
        
    )
    Process
    {
        $AddInfo = New-SDObject -UserName $UserName -AceType $AceType -AccessMask $AccessMask
        foreach ($share in ($ShareInfo | select -Unique Computer, Name)) 
        {
            $AddInfo.Computer = $share.Computer
            $AddInfo.Name = $share.name
            $AddInfo.Description = $Share.Description
            $AddInfo | Set-Share
        }
    }
}

#endregion 

#region Add-SharePermission 

function Add-SharePermission ($user, $AceType, $AccessMask) 
{
    $ShareInfo = @($input); $ShareInfoNew = @()
    $AddInfo = New-SDObject $user $AceType $AccessMask
    foreach ($Share in ($ShareInfo | select -Unique Computer, Name)) 
    {
        $AddInfo.Name = $Share.name
        $AddInfo.Computer = $Share.Computer
        $AddInfo.Description = $Share.Description
        $ShareInfoNew = @($ShareInfo | ?{$_.name -eq $Share.name})
        $ShareInfoNew += $AddInfo
        $ShareInfoNew | Set-Share
    }
}

#endregion 

#region Remove-SharePermission 

function Remove-SharePermission ($user) 
{
    $shares = @($input)
    $shares | ? {$_.user -ne $user} | Set-Share
}

#endregion 

#endregion

